package testrj.serializer;

import java.io.StringWriter;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import testrj.domain.MethodToTest;
import testrj.domain.SerializedData;

public class JunitSerializer implements Serializer {
	private VelocityEngine ve;
	
	public JunitSerializer() {
		try {
			ve = new VelocityEngine();
			ve.setProperty("resource.loader", "class");
			ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
			ve.init();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public SerializedData serialize(Object inputObject) {
		try {
			MethodToTest mtt = (MethodToTest) inputObject;
			
			Template testCaseTemplate = ve.getTemplate("JUnitTestCase.vm");
			VelocityContext contextForTestCase = new VelocityContext();
			prepareTestCaseIn(contextForTestCase, mtt);
			StringWriter writerForTestCase = new StringWriter();
			testCaseTemplate.merge( contextForTestCase, writerForTestCase );
			
			Template testCaseMethodTemplate = ve.getTemplate("JUnitTestCase_Method.vm");
			VelocityContext contextForTestCaseMethod = new VelocityContext();
			prepareTestCaseMethodIn(contextForTestCaseMethod, mtt);
			StringWriter writerForTestCaseMethod = new StringWriter();
			testCaseMethodTemplate.merge( contextForTestCaseMethod, writerForTestCaseMethod );
			
	        return new SerializedData(writerForTestCase.toString().replace("// testrj - new test case goes here", writerForTestCaseMethod.toString()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private void prepareTestCaseMethodIn(VelocityContext context, MethodToTest mtt) {
		int numberOfMethods = 0;
		try {
			Class clazz = Class.forName(mtt.getObjectForObjectUnderTest().getClass().getName() + "Test");
			numberOfMethods = clazz.getMethods().length;
		} catch (ClassNotFoundException e) {
		}
		String newMethodName = mtt.getMethodName() + "_" + (numberOfMethods+1);
		context.put("TestMethodName", newMethodName);
		context.put("ClassObjectUnderTest", mtt.getObjectForObjectUnderTest().getClass().getSimpleName());
	}
	
	private void prepareTestCaseIn(VelocityContext context, MethodToTest mtt) {
		context.put("package", mtt.getObjectForObjectUnderTest().getClass().getPackage().getName());
		context.put("TestClassName", mtt.getObjectForObjectUnderTest().getClass().getSimpleName() + "Test");
	}

	public Object deSerialize(SerializedData serializedInput) {
		return null;
	}
}